//
//  BirthdayCalculateModel.swift
//  FearfulNotification
//
//  Created by 筱鹏 on 2018/1/17.
//  Copyright © 2018年 筱鹏. All rights reserved.
//

import UIKit

extension BirthdayEntity {
    func configAlertAndChangeStatus(_ isOpen: Bool, _ complete: @escaping (BirthdayStatus) -> Void) {
        func changeSelfAlertStatus(_ isOpen: Bool, _ finish: @escaping (Bool)->Void) {
            self.execute.change({ (success) in
                finish(success)
            }) { (entity) in
                entity.alert = isOpen
            }
        }
        
        configAlert(isOpen, needHint: true) { (status) in
            if isOpen && status == .correct {
                changeSelfAlertStatus(true, { (success) in
                    complete(status)
                })
            } else {
                changeSelfAlertStatus(false, { (success) in
                    complete(status)
                })
            }
        }
    }
    
    func configAlert(_ isOpen: Bool, needHint: Bool, _ complete: @escaping (BirthdayStatus) -> Void) {
        let calculate = BirthdayCalculateModel()
        if isOpen {
            calculate.addBirthdayAlert(month: self.birthdayMonth,
                                       day: self.birthdayDay,
                                       name: self.name ?? "",
                                       desc: self.desc ?? "",
                                       birthdayId: self.birthdayId,
                                       needHint: needHint) { (status) in
                                        complete(status)
            }
        } else {
            calculate.removeBirthdayAlert(birthdayId: self.birthdayId)
            complete(.correct)
        }
    }
}

enum BirthdayStatus: Int {
    case correct        = 1     // 成功
    case incorrect              // 失败
    case today                  // 今天是生日时间
    case alreadyPass            // 生日今年已经过去了
    case none                   // 今年没有这个生日
}
/**
 * 读取coredata数据 转换为需要展示的数据
 * 开启通知，关闭通知
 * 每月可选择的农历日期
 * 本地存储bid
 */
class BirthdayCalculateModel: NSObject {
    
    let BirthdayAlertBaseID = "BirthdayAlertBaseID"
    
    let chineseCal: Calendar!
    let currenCal: Calendar!
    let dateFormater: DateFormatter!
    
    override init() {
        chineseCal = Calendar(identifier: .chinese)
        currenCal = Calendar.current
        dateFormater = DateFormatter()
        dateFormater.dateFormat = "yyyy-MM-dd"
        super.init()
    }
    
    /** 计算农历日期状态 */
    private func calculBirthdayStatus(dateCom: DateComponents, month: Int, day: Int) -> BirthdayStatus {
        let (success, allMonths, allDaysOfMonths) = calculAnyYearEveryMonthOfDays(dateCom)
        if !success {
            return .incorrect
        }
        let allDaysOptional = allDaysOfMonths[month]
        guard let allDays = allDaysOptional else { return .incorrect }
        // 当前年份是否包含此月份和天
        guard allMonths.contains(month) else { return .none }
        guard allDays.contains(day) else { return .none }
        
        let todayCom = chineseCal.dateComponents([.year], from: Date())
        if todayCom.year != dateCom.year {
            return .correct
        } else if month < dateCom.month! {
            return .alreadyPass
        } else if month == dateCom.month! {
            if day < dateCom.day! {
                return .alreadyPass
            } else if (day == dateCom.day!) {
                return .today
            } else {
                return .correct
            }
        } else {
            return .correct
        }
    }
    
    /** 计算dateCom中年份内的月份数和天数 */
    private func calculAnyYearEveryMonthOfDays(_ dateCom: DateComponents) -> (Bool, Range<Int>, [Int: Range<Int>])
    {
        let monthDate = chineseCal.date(from: dateCom)
        let monthsOptional = chineseCal.range(of: .month, in: .year, for: monthDate!)
        guard let months = monthsOptional else {
            return (false, 0..<0, [0: 0..<0])
        }
        var chineseDateCom = dateCom
        
        var monthDays: [Int:Range<Int>] = [:]
        for month in months {
            chineseDateCom.month = month
            chineseDateCom.day = 2
            let dayDate = chineseCal.date(from: chineseDateCom)
            let daysOptional = chineseCal.range(of: .day, in: .month, for: dayDate!)
            guard let days = daysOptional else {
                return (false, 0..<0, [0: 0..<0])
            }
            monthDays[month] = days
        }
        return (true, months, monthDays)
    }
}

//TODO: 查询日期数
extension BirthdayCalculateModel {
    
    /**
     * 获取待选择的月份组合和日期组合
     * @return (months: Range<Int>, days: Range<Int>)
     */
    func obtainMonthsAndDaysOfSelect() -> (Range<Int>, Range<Int>) {
        return (1..<13, 1..<31)
    }
}

//TODO: 开关生日提醒
extension BirthdayCalculateModel {
    func birthdayIdentifier(_ birthdayId: Int64) -> String {
        return BirthdayAlertBaseID + "\(birthdayId)"
    }
    
    func openAllBirthdayAlert() {
        let entitys = BirthdayEntity.execute.fetchAll("birthdayId", true)
        for entity in entitys {
            if entity.alert {
                entity.configAlert(true, needHint: false) { (status) in
                    Event.message("status = \(status)")
                }
            }
        }
    }
    
    func addBirthdayAlert(month: Int16,
                          day: Int16,
                          name: String,
                          desc: String,
                          birthdayId: Int64,
                          needHint: Bool,
                          complected: (BirthdayStatus)->Void)
    {
        // 计算 农历生日
        var dateCom = chineseCal.dateComponents([.year, .month, .day], from: Date())
        var status = calculBirthdayStatus(dateCom: dateCom, month: Int(month), day: Int(day))
        
        if status == .today && needHint {
            ProcessHUD.show(.hint, text: "Ta的生日就在今天")
        }
        
        let reCalcul: [BirthdayStatus] = [.alreadyPass, .none, .today]
        var limit = 0
        while reCalcul.contains(status) && limit < 5 {
            dateCom.year! += 1
            dateCom.month = 1
            dateCom.day = 1
            status = calculBirthdayStatus(dateCom: dateCom, month: Int(month), day: Int(day))
            limit += 1
        }
        
        if status != .correct {
            complected(status)
            return
        }
        dateCom.month = Int(month)
        dateCom.day = Int(day)
        
        let alertDate = chineseCal.date(from: dateCom)
        let alertTimeStr = dateFormater.string(from: alertDate!)
        var finalAlertDate = alertDate?.addingTimeInterval(BirthdayAlertOffsetTimeModel().currentOffsetTime.rawValue)
        
        let timeInterval = finalAlertDate!.timeIntervalSince(Date())
        if timeInterval <= 0 {
            if needHint {
                ProcessHUD.show(.hint, text: "设置的提醒时间已经发生，修改提醒时间为当天8点")
            }
            finalAlertDate = alertDate?.addingTimeInterval(BirthdayAlertOffsetTimeModel.OffsetTime.todayEight.rawValue)
        }
        
        let chinessTimeStr = String(format: "%02d-%02d", month, day)
        
        let title = "\(name)的生日提醒"
        #if DEBUG
        let dateFor = DateFormatter()
        dateFor.dateFormat = "yyyy-MM-dd HH:mm:ss"
        let body = "提醒时间: \(dateFor.string(from: finalAlertDate!)) 公历生日: \(alertTimeStr) 农历生日: \(chinessTimeStr)"+" 简介: \(desc)"
        #else
        let body = "公历生日: \(alertTimeStr) 农历生日: \(chinessTimeStr)"+" 简介: \(desc)"
        #endif
        LocalNotification.addOneDay(finalAlertDate!, title, body, nil, birthdayIdentifier(birthdayId), { (error) in
            guard let err = error else { return }
            Event.message("add location error \(err)")
        })
        complected(status)
    }
    
    func removeBirthdayAlert(birthdayId: Int64) {
        LocalNotification.remove(identifier: birthdayIdentifier(birthdayId))
    }
}
